﻿namespace TNet
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization.Formatters.Binary;
    using UnityEngine;

    public static class Serialization
    {
        public static BinaryFormatter formatter = new BinaryFormatter();
        private static Dictionary<System.Type, TNet.List<FieldInfo>> mFieldDict = new Dictionary<System.Type, TNet.List<FieldInfo>>();
        private static TNet.List<string> mFieldNames = new TNet.List<string>();
        private static TNet.List<object> mFieldValues = new TNet.List<object>();
        private static Dictionary<string, System.Type> mNameToType = new Dictionary<string, System.Type>();
        private static Dictionary<System.Type, string> mTypeToName = new Dictionary<System.Type, string>();

        public static object ConvertValue(object value, System.Type desiredType)
        {
            if (value != null)
            {
                System.Type c = value.GetType();
                if (desiredType.IsAssignableFrom(c))
                {
                    return value;
                }
                if (c == typeof(int))
                {
                    if (desiredType == typeof(byte))
                    {
                        return (byte) ((int) value);
                    }
                    if (desiredType == typeof(short))
                    {
                        return (short) ((int) value);
                    }
                    if (desiredType == typeof(ushort))
                    {
                        return (ushort) ((int) value);
                    }
                    if (desiredType == typeof(float))
                    {
                        return (float) ((int) value);
                    }
                }
                else if (c == typeof(float))
                {
                    if (desiredType == typeof(byte))
                    {
                        return (byte) Mathf.RoundToInt((float) value);
                    }
                    if (desiredType == typeof(short))
                    {
                        return (short) Mathf.RoundToInt((float) value);
                    }
                    if (desiredType == typeof(ushort))
                    {
                        return (ushort) Mathf.RoundToInt((float) value);
                    }
                    if (desiredType == typeof(int))
                    {
                        return Mathf.RoundToInt((float) value);
                    }
                }
                else if (c == typeof(Color32))
                {
                    if (desiredType == typeof(Color))
                    {
                        Color32 color = (Color32) value;
                        return new Color(((float) color.r) / 255f, ((float) color.g) / 255f, ((float) color.b) / 255f, ((float) color.a) / 255f);
                    }
                }
                else if (c == typeof(Vector3))
                {
                    if (desiredType == typeof(Color))
                    {
                        Vector3 vector = (Vector3) value;
                        return new Color(vector.x, vector.y, vector.z);
                    }
                    if (desiredType == typeof(Quaternion))
                    {
                        return Quaternion.Euler((Vector3) value);
                    }
                }
                else if (c == typeof(Color))
                {
                    if (desiredType == typeof(Quaternion))
                    {
                        Color color2 = (Color) value;
                        return new Quaternion(color2.r, color2.g, color2.b, color2.a);
                    }
                    if (desiredType == typeof(Rect))
                    {
                        Color color3 = (Color) value;
                        return new Rect(color3.r, color3.g, color3.b, color3.a);
                    }
                    if (desiredType == typeof(Vector4))
                    {
                        Color color4 = (Color) value;
                        return new Vector4(color4.r, color4.g, color4.b, color4.a);
                    }
                }
                if (desiredType.IsEnum)
                {
                    if (c == typeof(int))
                    {
                        return value;
                    }
                    if (c == typeof(string))
                    {
                        string str = (string) value;
                        if (!string.IsNullOrEmpty(str))
                        {
                            try
                            {
                                return Enum.Parse(desiredType, str);
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }
                }
                Debug.LogError(string.Concat(new object[] { "Unable to convert ", c, " to ", desiredType }));
            }
            return null;
        }

        public static object Create(this System.Type type)
        {
            try
            {
                return Activator.CreateInstance(type);
            }
            catch (Exception exception)
            {
                Debug.LogError(exception.Message);
                return null;
            }
        }

        public static object Create(this System.Type type, int size)
        {
            try
            {
                object[] args = new object[] { size };
                return Activator.CreateInstance(type, args);
            }
            catch (Exception)
            {
                return type.Create();
            }
        }

        public static int Deserialize(this object obj, string path)
        {
            FileStream output = File.Open(path, FileMode.Create);
            if (output == null)
            {
                return 0;
            }
            BinaryWriter bw = new BinaryWriter(output);
            bw.WriteObject(obj);
            int position = (int) output.Position;
            bw.Close();
            return position;
        }

        private static void FilterFields(object obj)
        {
            TNet.List<FieldInfo> serializableFields = obj.GetType().GetSerializableFields();
            mFieldNames.Clear();
            mFieldValues.Clear();
            for (int i = 0; i < serializableFields.size; i++)
            {
                FieldInfo info = serializableFields[i];
                object item = info.GetValue(obj);
                if (item != null)
                {
                    mFieldNames.Add(info.Name);
                    mFieldValues.Add(item);
                }
            }
        }

        private static void FilterFields(object obj, out TNet.List<string> fieldNames, out TNet.List<object> fieldValues)
        {
            TNet.List<FieldInfo> serializableFields = obj.GetType().GetSerializableFields();
            fieldNames = new TNet.List<string>();
            fieldValues = new TNet.List<object>();
            for (int i = 0; i < serializableFields.size; i++)
            {
                FieldInfo info = serializableFields[i];
                object item = info.GetValue(obj);
                if (item != null)
                {
                    fieldNames.Add(info.Name);
                    fieldValues.Add(item);
                }
            }
        }

        public static System.Type GetGenericArgument(this System.Type type)
        {
            System.Type[] genericArguments = type.GetGenericArguments();
            return (((genericArguments == null) || (genericArguments.Length != 1)) ? null : genericArguments[0]);
        }

        private static int GetPrefix(System.Type type)
        {
            if (type == typeof(bool))
            {
                return 1;
            }
            if (type == typeof(byte))
            {
                return 2;
            }
            if (type == typeof(ushort))
            {
                return 3;
            }
            if (type == typeof(int))
            {
                return 4;
            }
            if (type == typeof(uint))
            {
                return 5;
            }
            if (type == typeof(float))
            {
                return 6;
            }
            if (type == typeof(string))
            {
                return 7;
            }
            if (type == typeof(Vector2))
            {
                return 8;
            }
            if (type == typeof(Vector3))
            {
                return 9;
            }
            if (type == typeof(Vector4))
            {
                return 10;
            }
            if (type == typeof(Quaternion))
            {
                return 11;
            }
            if (type == typeof(Color32))
            {
                return 12;
            }
            if (type == typeof(Color))
            {
                return 13;
            }
            if (type == typeof(DataNode))
            {
                return 14;
            }
            if (type == typeof(double))
            {
                return 15;
            }
            if (type == typeof(short))
            {
                return 0x10;
            }
            if (type == typeof(TNObject))
            {
                return 0x11;
            }
            if (type == typeof(long))
            {
                return 0x12;
            }
            if (type == typeof(ulong))
            {
                return 0x13;
            }
            if (type == typeof(bool[]))
            {
                return 0x65;
            }
            if (type == typeof(byte[]))
            {
                return 0x66;
            }
            if (type == typeof(ushort[]))
            {
                return 0x67;
            }
            if (type == typeof(int[]))
            {
                return 0x68;
            }
            if (type == typeof(uint[]))
            {
                return 0x69;
            }
            if (type == typeof(float[]))
            {
                return 0x6a;
            }
            if (type == typeof(string[]))
            {
                return 0x6b;
            }
            if (type == typeof(Vector2[]))
            {
                return 0x6c;
            }
            if (type == typeof(Vector3[]))
            {
                return 0x6d;
            }
            if (type == typeof(Vector4[]))
            {
                return 110;
            }
            if (type == typeof(Quaternion[]))
            {
                return 0x6f;
            }
            if (type == typeof(Color32[]))
            {
                return 0x70;
            }
            if (type == typeof(Color[]))
            {
                return 0x71;
            }
            if (type == typeof(double[]))
            {
                return 0x73;
            }
            if (type == typeof(short[]))
            {
                return 0x74;
            }
            if (type == typeof(TNObject[]))
            {
                return 0x75;
            }
            if (type == typeof(long[]))
            {
                return 0x76;
            }
            if (type == typeof(ulong[]))
            {
                return 0x77;
            }
            return 0xfe;
        }

        public static FieldInfo GetSerializableField(this System.Type type, string name)
        {
            TNet.List<FieldInfo> serializableFields = type.GetSerializableFields();
            int num = 0;
            int size = serializableFields.size;
            while (num < size)
            {
                FieldInfo info = serializableFields[num];
                if (info.Name == name)
                {
                    return info;
                }
                num++;
            }
            return null;
        }

        public static TNet.List<FieldInfo> GetSerializableFields(this System.Type type)
        {
            TNet.List<FieldInfo> list;
            if (!mFieldDict.TryGetValue(type, out list))
            {
                list = new TNet.List<FieldInfo>();
                FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                bool flag = type.IsDefined(typeof(SerializableAttribute), true);
                int index = 0;
                int length = fields.Length;
                while (index < length)
                {
                    FieldInfo item = fields[index];
                    if ((((item.Attributes & FieldAttributes.Static) == FieldAttributes.PrivateScope) && (item.IsDefined(typeof(SerializeField), true) || (flag && ((item.Attributes & FieldAttributes.Public) != FieldAttributes.PrivateScope)))) && !item.IsDefined(typeof(NonSerializedAttribute), true))
                    {
                        list.Add(item);
                    }
                    index++;
                }
                mFieldDict[type] = list;
            }
            return list;
        }

        private static System.Type GetType(int prefix)
        {
            switch (prefix)
            {
                case 1:
                    return typeof(bool);

                case 2:
                    return typeof(byte);

                case 3:
                    return typeof(ushort);

                case 4:
                    return typeof(int);

                case 5:
                    return typeof(uint);

                case 6:
                    return typeof(float);

                case 7:
                    return typeof(string);

                case 8:
                    return typeof(Vector2);

                case 9:
                    return typeof(Vector3);

                case 10:
                    return typeof(Vector4);

                case 11:
                    return typeof(Quaternion);

                case 12:
                    return typeof(Color32);

                case 13:
                    return typeof(Color);

                case 14:
                    return typeof(DataNode);

                case 15:
                    return typeof(double);

                case 0x10:
                    return typeof(short);

                case 0x11:
                    return typeof(TNObject);

                case 0x12:
                    return typeof(long);

                case 0x13:
                    return typeof(ulong);

                case 0x65:
                    return typeof(bool[]);

                case 0x66:
                    return typeof(byte[]);

                case 0x67:
                    return typeof(ushort[]);

                case 0x68:
                    return typeof(int[]);

                case 0x69:
                    return typeof(uint[]);

                case 0x6a:
                    return typeof(float[]);

                case 0x6b:
                    return typeof(string[]);

                case 0x6c:
                    return typeof(Vector2[]);

                case 0x6d:
                    return typeof(Vector3[]);

                case 110:
                    return typeof(Vector4[]);

                case 0x6f:
                    return typeof(Quaternion[]);

                case 0x70:
                    return typeof(Color32[]);

                case 0x71:
                    return typeof(Color[]);

                case 0x73:
                    return typeof(double[]);

                case 0x74:
                    return typeof(short[]);

                case 0x75:
                    return typeof(TNObject[]);

                case 0x76:
                    return typeof(long[]);

                case 0x77:
                    return typeof(ulong[]);
            }
            return null;
        }

        public static bool Implements(this System.Type t, System.Type interfaceType)
        {
            if (interfaceType == null)
            {
                return false;
            }
            return interfaceType.IsAssignableFrom(t);
        }

        public static System.Type NameToType(string name)
        {
            System.Type type = null;
            if (!mNameToType.TryGetValue(name, out type))
            {
                if (name == "Vector2")
                {
                    type = typeof(Vector2);
                }
                else if (name == "Vector3")
                {
                    type = typeof(Vector3);
                }
                else if (name == "Vector4")
                {
                    type = typeof(Vector4);
                }
                else if ((name == "Euler") || (name == "Quaternion"))
                {
                    type = typeof(Quaternion);
                }
                else if (name == "Rect")
                {
                    type = typeof(Rect);
                }
                else if (name == "Color")
                {
                    type = typeof(Color);
                }
                else if (name == "Color32")
                {
                    type = typeof(Color32);
                }
                else if (name == "string[]")
                {
                    type = typeof(string[]);
                }
                else if (name.StartsWith("IList"))
                {
                    if (((name.Length > 7) && (name[5] == '<')) && (name[name.Length - 1] == '>'))
                    {
                        System.Type type2 = NameToType(name.Substring(6, name.Length - 7));
                        System.Type[] typeArguments = new System.Type[] { type2 };
                        type = typeof(System.Collections.Generic.List<>).MakeGenericType(typeArguments);
                    }
                    else
                    {
                        Debug.LogWarning("Malformed type: " + name);
                    }
                }
                else if (name.StartsWith("TList"))
                {
                    if (((name.Length > 7) && (name[5] == '<')) && (name[name.Length - 1] == '>'))
                    {
                        System.Type type3 = NameToType(name.Substring(6, name.Length - 7));
                        System.Type[] typeArray2 = new System.Type[] { type3 };
                        type = typeof(TNet.List<>).MakeGenericType(typeArray2);
                    }
                    else
                    {
                        Debug.LogWarning("Malformed type: " + name);
                    }
                }
                else
                {
                    type = System.Type.GetType(name);
                }
                mNameToType[name] = type;
            }
            return type;
        }

        public static Color ReadColor(this BinaryReader reader)
        {
            return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }

        public static Color32 ReadColor32(this BinaryReader reader)
        {
            return new Color32(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
        }

        public static DataNode ReadDataNode(this BinaryReader reader)
        {
            string str = reader.ReadString();
            if (string.IsNullOrEmpty(str))
            {
                return null;
            }
            DataNode node = new DataNode {
                name = str,
                value = reader.ReadObject()
            };
            int num = reader.ReadInt();
            for (int i = 0; i < num; i++)
            {
                node.children.Add(reader.ReadDataNode());
            }
            return node;
        }

        public static int ReadInt(this BinaryReader reader)
        {
            int num = reader.ReadByte();
            if (num == 0xff)
            {
                num = reader.ReadInt32();
            }
            return num;
        }

        public static object ReadObject(this BinaryReader reader)
        {
            return reader.ReadObject(null, 0, null, false);
        }

        public static T ReadObject<T>(this BinaryReader reader)
        {
            object obj2 = reader.ReadObject();
            if (obj2 == null)
            {
                return default(T);
            }
            return (T) obj2;
        }

        public static object ReadObject(this BinaryReader reader, object obj)
        {
            return reader.ReadObject(obj, 0, null, false);
        }

        private static object ReadObject(this BinaryReader reader, object obj, int prefix, System.Type type, bool typeIsKnown)
        {
            bool flag;
            int num;
            TList list;
            if (!typeIsKnown)
            {
                type = reader.ReadType(out prefix);
            }
            if (type.Implements(typeof(IBinarySerializable)))
            {
                prefix = 0xfd;
            }
            int num44 = prefix;
            switch (num44)
            {
                case 0x62:
                    type = reader.ReadType(out prefix);
                    flag = reader.ReadByte() == 1;
                    num = reader.ReadInt();
                    list = null;
                    if (obj == null)
                    {
                        System.Type[] typeArguments = new System.Type[] { type };
                        list = (TList) Activator.CreateInstance(typeof(TNet.List<>).MakeGenericType(typeArguments));
                    }
                    else
                    {
                        list = (TList) obj;
                    }
                    break;

                case 0x63:
                {
                    type = reader.ReadType(out prefix);
                    bool flag2 = reader.ReadByte() == 1;
                    int num3 = reader.ReadInt();
                    IList list2 = null;
                    if (obj == null)
                    {
                        System.Type[] typeArray2 = new System.Type[] { type };
                        list2 = (IList) Activator.CreateInstance(typeof(System.Collections.Generic.List<>).MakeGenericType(typeArray2));
                    }
                    else
                    {
                        list2 = (IList) obj;
                    }
                    for (int j = 0; j < num3; j++)
                    {
                        object obj3 = reader.ReadObject(null, prefix, type, flag2);
                        if (list2 != null)
                        {
                            list2.Add(obj3);
                        }
                    }
                    return list2;
                }
                case 100:
                {
                    type = reader.ReadType(out prefix);
                    bool flag3 = reader.ReadByte() == 1;
                    int size = reader.ReadInt();
                    IList list3 = (IList) type.Create(size);
                    if (list3 == null)
                    {
                        Debug.LogError("Failed to create a " + type);
                        return list3;
                    }
                    type = type.GetElementType();
                    prefix = GetPrefix(type);
                    for (int k = 0; k < size; k++)
                    {
                        list3[k] = reader.ReadObject(null, prefix, type, flag3);
                    }
                    return list3;
                }
                case 0x65:
                {
                    int num7 = reader.ReadInt();
                    bool[] flagArray = new bool[num7];
                    for (int m = 0; m < num7; m++)
                    {
                        flagArray[m] = reader.ReadBoolean();
                    }
                    return flagArray;
                }
                case 0x66:
                {
                    int count = reader.ReadInt();
                    return reader.ReadBytes(count);
                }
                case 0x67:
                {
                    int num10 = reader.ReadInt();
                    ushort[] numArray = new ushort[num10];
                    for (int n = 0; n < num10; n++)
                    {
                        numArray[n] = reader.ReadUInt16();
                    }
                    return numArray;
                }
                case 0x68:
                {
                    int num12 = reader.ReadInt();
                    int[] numArray2 = new int[num12];
                    for (int num13 = 0; num13 < num12; num13++)
                    {
                        numArray2[num13] = reader.ReadInt32();
                    }
                    return numArray2;
                }
                case 0x69:
                {
                    int num14 = reader.ReadInt();
                    uint[] numArray3 = new uint[num14];
                    for (int num15 = 0; num15 < num14; num15++)
                    {
                        numArray3[num15] = reader.ReadUInt32();
                    }
                    return numArray3;
                }
                case 0x6a:
                {
                    int num16 = reader.ReadInt();
                    float[] numArray4 = new float[num16];
                    for (int num17 = 0; num17 < num16; num17++)
                    {
                        numArray4[num17] = reader.ReadSingle();
                    }
                    return numArray4;
                }
                case 0x6b:
                {
                    int num18 = reader.ReadInt();
                    string[] strArray = new string[num18];
                    for (int num19 = 0; num19 < num18; num19++)
                    {
                        strArray[num19] = reader.ReadString();
                    }
                    return strArray;
                }
                case 0x6c:
                {
                    int num20 = reader.ReadInt();
                    Vector2[] vectorArray = new Vector2[num20];
                    for (int num21 = 0; num21 < num20; num21++)
                    {
                        vectorArray[num21] = reader.ReadVector2();
                    }
                    return vectorArray;
                }
                case 0x6d:
                {
                    int num22 = reader.ReadInt();
                    Vector3[] vectorArray2 = new Vector3[num22];
                    for (int num23 = 0; num23 < num22; num23++)
                    {
                        vectorArray2[num23] = reader.ReadVector3();
                    }
                    return vectorArray2;
                }
                case 110:
                {
                    int num24 = reader.ReadInt();
                    Vector4[] vectorArray3 = new Vector4[num24];
                    for (int num25 = 0; num25 < num24; num25++)
                    {
                        vectorArray3[num25] = reader.ReadVector4();
                    }
                    return vectorArray3;
                }
                case 0x6f:
                {
                    int num26 = reader.ReadInt();
                    Quaternion[] quaternionArray = new Quaternion[num26];
                    for (int num27 = 0; num27 < num26; num27++)
                    {
                        quaternionArray[num27] = reader.ReadQuaternion();
                    }
                    return quaternionArray;
                }
                case 0x70:
                {
                    int num28 = reader.ReadInt();
                    Color32[] colorArray = new Color32[num28];
                    for (int num29 = 0; num29 < num28; num29++)
                    {
                        colorArray[num29] = reader.ReadColor32();
                    }
                    return colorArray;
                }
                case 0x71:
                {
                    int num30 = reader.ReadInt();
                    Color[] colorArray2 = new Color[num30];
                    for (int num31 = 0; num31 < num30; num31++)
                    {
                        colorArray2[num31] = reader.ReadColor();
                    }
                    return colorArray2;
                }
                case 0x73:
                {
                    int num32 = reader.ReadInt();
                    double[] numArray5 = new double[num32];
                    for (int num33 = 0; num33 < num32; num33++)
                    {
                        numArray5[num33] = reader.ReadDouble();
                    }
                    return numArray5;
                }
                case 0x74:
                {
                    int num34 = reader.ReadInt();
                    short[] numArray6 = new short[num34];
                    for (int num35 = 0; num35 < num34; num35++)
                    {
                        numArray6[num35] = reader.ReadInt16();
                    }
                    return numArray6;
                }
                case 0x75:
                {
                    int num36 = reader.ReadInt();
                    TNObject[] objArray = new TNObject[num36];
                    for (int num37 = 0; num37 < num36; num37++)
                    {
                        objArray[num37] = TNObject.Find(reader.ReadUInt32());
                    }
                    return objArray;
                }
                case 0x76:
                {
                    int num38 = reader.ReadInt();
                    long[] numArray7 = new long[num38];
                    for (int num39 = 0; num39 < num38; num39++)
                    {
                        numArray7[num39] = reader.ReadInt64();
                    }
                    return numArray7;
                }
                case 0x77:
                {
                    int num40 = reader.ReadInt();
                    ulong[] numArray8 = new ulong[num40];
                    for (int num41 = 0; num41 < num40; num41++)
                    {
                        numArray8[num41] = reader.ReadUInt64();
                    }
                    return numArray8;
                }
                default:
                    switch (num44)
                    {
                        case 0:
                            return null;

                        case 1:
                            return reader.ReadBoolean();

                        case 2:
                            return reader.ReadByte();

                        case 3:
                            return reader.ReadUInt16();

                        case 4:
                            return reader.ReadInt32();

                        case 5:
                            return reader.ReadUInt32();

                        case 6:
                            return reader.ReadSingle();

                        case 7:
                            return reader.ReadString();

                        case 8:
                            return reader.ReadVector2();

                        case 9:
                            return reader.ReadVector3();

                        case 10:
                            return reader.ReadVector4();

                        case 11:
                            return reader.ReadQuaternion();

                        case 12:
                            return reader.ReadColor32();

                        case 13:
                            return reader.ReadColor();

                        case 14:
                            return reader.ReadDataNode();

                        case 15:
                            return reader.ReadDouble();

                        case 0x10:
                            return reader.ReadInt16();

                        case 0x11:
                            return TNObject.Find(reader.ReadUInt32());

                        case 0x12:
                            return reader.ReadInt64();

                        case 0x13:
                            return reader.ReadUInt64();

                        default:
                            switch (num44)
                            {
                                case 0xfd:
                                {
                                    IBinarySerializable serializable = (obj == null) ? ((IBinarySerializable) type.Create()) : ((IBinarySerializable) obj);
                                    if (serializable != null)
                                    {
                                        serializable.Deserialize(reader);
                                    }
                                    return serializable;
                                }
                                case 0xfe:
                                    if (obj == null)
                                    {
                                        obj = type.Create();
                                        if (obj == null)
                                        {
                                            Debug.LogError("Unable to create an instance of " + type);
                                        }
                                    }
                                    if (obj != null)
                                    {
                                        int num42 = reader.ReadInt();
                                        for (int num43 = 0; num43 < num42; num43++)
                                        {
                                            string str = reader.ReadString();
                                            if (string.IsNullOrEmpty(str))
                                            {
                                                Debug.LogError("Null field specified when serializing " + type);
                                            }
                                            else
                                            {
                                                FieldInfo field = type.GetField(str, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                                                object obj4 = reader.ReadObject();
                                                if (field != null)
                                                {
                                                    field.SetValue(obj, ConvertValue(obj4, field.FieldType));
                                                }
                                                else
                                                {
                                                    Debug.LogError(string.Concat(new object[] { "Unable to set field ", type, ".", str }));
                                                }
                                            }
                                        }
                                    }
                                    return obj;

                                case 0xff:
                                    return formatter.Deserialize(reader.BaseStream);
                            }
                            Debug.LogError("Unknown prefix: " + prefix);
                            return null;
                    }
                    break;
            }
            for (int i = 0; i < num; i++)
            {
                object obj2 = reader.ReadObject(null, prefix, type, flag);
                if (list != null)
                {
                    list.Add(obj2);
                }
            }
            return list;
        }

        public static Quaternion ReadQuaternion(this BinaryReader reader)
        {
            return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }

        public static System.Type ReadType(this BinaryReader reader)
        {
            int prefix = reader.ReadByte();
            return ((prefix <= 250) ? GetType(prefix) : NameToType(reader.ReadString()));
        }

        public static System.Type ReadType(this BinaryReader reader, out int prefix)
        {
            prefix = reader.ReadByte();
            return ((prefix <= 250) ? GetType(prefix) : NameToType(reader.ReadString()));
        }

        public static Vector2 ReadVector2(this BinaryReader reader)
        {
            return new Vector2(reader.ReadSingle(), reader.ReadSingle());
        }

        public static Vector3 ReadVector3(this BinaryReader reader)
        {
            return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }

        public static Vector4 ReadVector4(this BinaryReader reader)
        {
            return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }

        public static bool SetSerializableField(this object obj, string name, object value)
        {
            if (obj == null)
            {
                return false;
            }
            FieldInfo serializableField = obj.GetType().GetSerializableField(name);
            if (serializableField == null)
            {
                return false;
            }
            try
            {
                serializableField.SetValue(obj, ConvertValue(value, serializableField.FieldType));
            }
            catch (Exception exception)
            {
                Debug.LogError(exception.Message);
                return false;
            }
            return true;
        }

        public static string TypeToName(System.Type type)
        {
            string str;
            if (type == null)
            {
                Debug.LogError("Type cannot be null");
                return null;
            }
            if (!mTypeToName.TryGetValue(type, out str))
            {
                if (type == typeof(Vector2))
                {
                    str = "Vector2";
                }
                else if (type == typeof(Vector3))
                {
                    str = "Vector3";
                }
                else if (type == typeof(Vector4))
                {
                    str = "Vector4";
                }
                else if (type == typeof(Quaternion))
                {
                    str = "Euler";
                }
                else if (type == typeof(Rect))
                {
                    str = "Rect";
                }
                else if (type == typeof(Color))
                {
                    str = "Color";
                }
                else if (type == typeof(Color32))
                {
                    str = "Color32";
                }
                else if (type == typeof(string[]))
                {
                    str = "string[]";
                }
                else if (type.Implements(typeof(IList)))
                {
                    System.Type genericArgument = type.GetGenericArgument();
                    if (genericArgument != null)
                    {
                        str = "IList<" + genericArgument.ToString() + ">";
                    }
                    else
                    {
                        str = type.ToString();
                    }
                }
                else if (type.Implements(typeof(TList)))
                {
                    System.Type type3 = type.GetGenericArgument();
                    if (type3 != null)
                    {
                        str = "TList<" + type3.ToString() + ">";
                    }
                    else
                    {
                        str = type.ToString();
                    }
                }
                else
                {
                    str = type.ToString();
                }
                mTypeToName[type] = str;
            }
            return str;
        }

        public static void Write(this BinaryWriter bw, System.Type type)
        {
            int prefix = GetPrefix(type);
            bw.Write((byte) prefix);
            if (prefix > 250)
            {
                bw.Write(TypeToName(type));
            }
        }

        public static void Write(this BinaryWriter writer, DataNode node)
        {
            if ((node == null) || string.IsNullOrEmpty(node.name))
            {
                writer.Write(string.Empty);
            }
            else
            {
                writer.Write(node.name);
                writer.WriteObject(node.value);
                writer.WriteInt(node.children.size);
                int num = 0;
                int size = node.children.size;
                while (num < size)
                {
                    writer.Write(node.children[num]);
                    num++;
                }
            }
        }

        public static void Write(this BinaryWriter writer, Color c)
        {
            writer.Write(c.r);
            writer.Write(c.g);
            writer.Write(c.b);
            writer.Write(c.a);
        }

        public static void Write(this BinaryWriter writer, Color32 c)
        {
            writer.Write(c.r);
            writer.Write(c.g);
            writer.Write(c.b);
            writer.Write(c.a);
        }

        public static void Write(this BinaryWriter writer, Quaternion q)
        {
            writer.Write(q.x);
            writer.Write(q.y);
            writer.Write(q.z);
            writer.Write(q.w);
        }

        public static void Write(this BinaryWriter writer, Vector2 v)
        {
            writer.Write(v.x);
            writer.Write(v.y);
        }

        public static void Write(this BinaryWriter writer, Vector3 v)
        {
            writer.Write(v.x);
            writer.Write(v.y);
            writer.Write(v.z);
        }

        public static void Write(this BinaryWriter writer, Vector4 v)
        {
            writer.Write(v.x);
            writer.Write(v.y);
            writer.Write(v.z);
            writer.Write(v.w);
        }

        public static void Write(this BinaryWriter bw, int prefix, System.Type type)
        {
            bw.Write((byte) prefix);
            if (prefix > 250)
            {
                bw.Write(TypeToName(type));
            }
        }

        public static void WriteInt(this BinaryWriter bw, int val)
        {
            if ((val < 0xff) && (val > -1))
            {
                bw.Write((byte) val);
            }
            else
            {
                bw.Write((byte) 0xff);
                bw.Write(val);
            }
        }

        public static void WriteObject(this BinaryWriter bw, object obj)
        {
            bw.WriteObject(obj, 0xff, false, true);
        }

        public static void WriteObject(this BinaryWriter bw, object obj, bool useReflection)
        {
            bw.WriteObject(obj, 0xff, false, useReflection);
        }

        private static void WriteObject(this BinaryWriter bw, object obj, int prefix, bool typeIsKnown, bool useReflection)
        {
            System.Type type;
            bool flag2;
            int num6;
            IList list2;
            bool flag3;
            if (obj == null)
            {
                bw.Write((byte) 0);
                return;
            }
            if (obj is IBinarySerializable)
            {
                if (!typeIsKnown)
                {
                    bw.Write(0xfd, obj.GetType());
                }
                (obj as IBinarySerializable).Serialize(bw);
                return;
            }
            if (!typeIsKnown)
            {
                type = obj.GetType();
                prefix = GetPrefix(type);
            }
            else
            {
                type = GetType(prefix);
            }
            if (prefix <= 250)
            {
                goto Label_02DE;
            }
            if (obj is TList)
            {
                if (useReflection)
                {
                    System.Type genericArgument = type.GetGenericArgument();
                    if (genericArgument != null)
                    {
                        TList list = obj as TList;
                        int num = GetPrefix(genericArgument);
                        bool flag = true;
                        int index = 0;
                        int count = list.Count;
                        while (index < count)
                        {
                            object obj2 = list.Get(index);
                            if ((obj2 != null) && (genericArgument != obj2.GetType()))
                            {
                                flag = false;
                                num = 0xff;
                                break;
                            }
                            index++;
                        }
                        if (!typeIsKnown)
                        {
                            bw.Write((byte) 0x62);
                        }
                        bw.Write(genericArgument);
                        bw.Write(!flag ? ((byte) 0) : ((byte) 1));
                        bw.WriteInt(list.Count);
                        int num4 = 0;
                        int num5 = list.Count;
                        while (num4 < num5)
                        {
                            bw.WriteObject(list.Get(num4), num, flag, useReflection);
                            num4++;
                        }
                        return;
                    }
                }
                if (!typeIsKnown)
                {
                    bw.Write((byte) 0xff);
                }
                formatter.Serialize(bw.BaseStream, obj);
                return;
            }
            else
            {
                if (!(obj is IList))
                {
                    goto Label_02DE;
                }
                if (!useReflection)
                {
                    goto Label_02BB;
                }
                System.Type elementType = type.GetGenericArgument();
                flag2 = false;
                if (elementType == null)
                {
                    elementType = type.GetElementType();
                    flag2 = type != null;
                }
                if (!flag2 && (elementType == null))
                {
                    goto Label_02BB;
                }
                num6 = GetPrefix(elementType);
                list2 = obj as IList;
                flag3 = true;
                IEnumerator enumerator = list2.GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        object current = enumerator.Current;
                        if ((current != null) && (elementType != current.GetType()))
                        {
                            flag3 = false;
                            num6 = 0xff;
                            goto Label_0229;
                        }
                    }
                }
                finally
                {
                    IDisposable disposable = enumerator as IDisposable;
                    if (disposable == null)
                    {
                    }
                    disposable.Dispose();
                }
            }
        Label_0229:
            if (!typeIsKnown)
            {
                bw.Write(!flag2 ? ((byte) 0x63) : ((byte) 100));
            }
            bw.Write(type);
            bw.Write(!flag3 ? ((byte) 0) : ((byte) 1));
            bw.WriteInt(list2.Count);
            IEnumerator enumerator2 = list2.GetEnumerator();
            try
            {
                while (enumerator2.MoveNext())
                {
                    object obj4 = enumerator2.Current;
                    bw.WriteObject(obj4, num6, flag3, useReflection);
                }
            }
            finally
            {
                IDisposable disposable2 = enumerator2 as IDisposable;
                if (disposable2 == null)
                {
                }
                disposable2.Dispose();
            }
            return;
        Label_02BB:
            if (!typeIsKnown)
            {
                bw.Write((byte) 0xff);
            }
            formatter.Serialize(bw.BaseStream, obj);
            return;
        Label_02DE:
            if (!typeIsKnown)
            {
                bw.Write(prefix, type);
            }
            int num41 = prefix;
            switch (num41)
            {
                case 1:
                    bw.Write((bool) obj);
                    return;

                case 2:
                    bw.Write((byte) obj);
                    return;

                case 3:
                    bw.Write((ushort) obj);
                    return;

                case 4:
                    bw.Write((int) obj);
                    return;

                case 5:
                    bw.Write((uint) obj);
                    return;

                case 6:
                    bw.Write((float) obj);
                    return;

                case 7:
                    bw.Write((string) obj);
                    return;

                case 8:
                    bw.Write((Vector2) obj);
                    return;

                case 9:
                    bw.Write((Vector3) obj);
                    return;

                case 10:
                    bw.Write((Vector4) obj);
                    return;

                case 11:
                    bw.Write((Quaternion) obj);
                    return;

                case 12:
                    bw.Write((Color32) obj);
                    return;

                case 13:
                    bw.Write((Color) obj);
                    return;

                case 14:
                    bw.Write((DataNode) obj);
                    return;

                case 15:
                    bw.Write((double) obj);
                    return;

                case 0x10:
                    bw.Write((short) obj);
                    return;

                case 0x11:
                    bw.Write((obj as TNObject).uid);
                    return;

                case 0x12:
                    bw.Write((long) obj);
                    return;

                case 0x65:
                {
                    bool[] flagArray = (bool[]) obj;
                    bw.WriteInt(flagArray.Length);
                    int num7 = 0;
                    int length = flagArray.Length;
                    while (num7 < length)
                    {
                        bw.Write(flagArray[num7]);
                        num7++;
                    }
                    return;
                }
                case 0x66:
                {
                    byte[] buffer = (byte[]) obj;
                    bw.WriteInt(buffer.Length);
                    bw.Write(buffer);
                    return;
                }
                case 0x67:
                {
                    ushort[] numArray = (ushort[]) obj;
                    bw.WriteInt(numArray.Length);
                    int num9 = 0;
                    int num10 = numArray.Length;
                    while (num9 < num10)
                    {
                        bw.Write(numArray[num9]);
                        num9++;
                    }
                    return;
                }
                case 0x68:
                {
                    int[] numArray2 = (int[]) obj;
                    bw.WriteInt(numArray2.Length);
                    int num11 = 0;
                    int num12 = numArray2.Length;
                    while (num11 < num12)
                    {
                        bw.Write(numArray2[num11]);
                        num11++;
                    }
                    return;
                }
                case 0x69:
                {
                    uint[] numArray3 = (uint[]) obj;
                    bw.WriteInt(numArray3.Length);
                    int num13 = 0;
                    int num14 = numArray3.Length;
                    while (num13 < num14)
                    {
                        bw.Write(numArray3[num13]);
                        num13++;
                    }
                    return;
                }
                case 0x6a:
                {
                    float[] numArray4 = (float[]) obj;
                    bw.WriteInt(numArray4.Length);
                    int num15 = 0;
                    int num16 = numArray4.Length;
                    while (num15 < num16)
                    {
                        bw.Write(numArray4[num15]);
                        num15++;
                    }
                    return;
                }
                case 0x6b:
                {
                    string[] strArray = (string[]) obj;
                    bw.WriteInt(strArray.Length);
                    int num17 = 0;
                    int num18 = strArray.Length;
                    while (num17 < num18)
                    {
                        bw.Write(strArray[num17]);
                        num17++;
                    }
                    return;
                }
                case 0x6c:
                {
                    Vector2[] vectorArray = (Vector2[]) obj;
                    bw.WriteInt(vectorArray.Length);
                    int num19 = 0;
                    int num20 = vectorArray.Length;
                    while (num19 < num20)
                    {
                        bw.Write(vectorArray[num19]);
                        num19++;
                    }
                    return;
                }
                case 0x6d:
                {
                    Vector3[] vectorArray2 = (Vector3[]) obj;
                    bw.WriteInt(vectorArray2.Length);
                    int num21 = 0;
                    int num22 = vectorArray2.Length;
                    while (num21 < num22)
                    {
                        bw.Write(vectorArray2[num21]);
                        num21++;
                    }
                    return;
                }
                case 110:
                {
                    Vector4[] vectorArray3 = (Vector4[]) obj;
                    bw.WriteInt(vectorArray3.Length);
                    int num23 = 0;
                    int num24 = vectorArray3.Length;
                    while (num23 < num24)
                    {
                        bw.Write(vectorArray3[num23]);
                        num23++;
                    }
                    return;
                }
                case 0x6f:
                {
                    Quaternion[] quaternionArray = (Quaternion[]) obj;
                    bw.WriteInt(quaternionArray.Length);
                    int num25 = 0;
                    int num26 = quaternionArray.Length;
                    while (num25 < num26)
                    {
                        bw.Write(quaternionArray[num25]);
                        num25++;
                    }
                    return;
                }
                case 0x70:
                {
                    Color32[] colorArray = (Color32[]) obj;
                    bw.WriteInt(colorArray.Length);
                    int num27 = 0;
                    int num28 = colorArray.Length;
                    while (num27 < num28)
                    {
                        bw.Write(colorArray[num27]);
                        num27++;
                    }
                    return;
                }
                case 0x71:
                {
                    Color[] colorArray2 = (Color[]) obj;
                    bw.WriteInt(colorArray2.Length);
                    int num29 = 0;
                    int num30 = colorArray2.Length;
                    while (num29 < num30)
                    {
                        bw.Write(colorArray2[num29]);
                        num29++;
                    }
                    return;
                }
                case 0x73:
                {
                    double[] numArray5 = (double[]) obj;
                    bw.WriteInt(numArray5.Length);
                    int num31 = 0;
                    int num32 = numArray5.Length;
                    while (num31 < num32)
                    {
                        bw.Write(numArray5[num31]);
                        num31++;
                    }
                    return;
                }
                case 0x74:
                {
                    short[] numArray6 = (short[]) obj;
                    bw.WriteInt(numArray6.Length);
                    int num33 = 0;
                    int num34 = numArray6.Length;
                    while (num33 < num34)
                    {
                        bw.Write(numArray6[num33]);
                        num33++;
                    }
                    return;
                }
                case 0x75:
                {
                    TNObject[] objArray = (TNObject[]) obj;
                    bw.WriteInt(objArray.Length);
                    int num35 = 0;
                    int num36 = objArray.Length;
                    while (num35 < num36)
                    {
                        bw.Write(objArray[num35].uid);
                        num35++;
                    }
                    return;
                }
                case 0x76:
                {
                    long[] numArray7 = (long[]) obj;
                    bw.WriteInt(numArray7.Length);
                    int num37 = 0;
                    int num38 = numArray7.Length;
                    while (num37 < num38)
                    {
                        bw.Write(numArray7[num37]);
                        num37++;
                    }
                    return;
                }
            }
            switch (num41)
            {
                case 0xfe:
                {
                    TNet.List<string> list3;
                    TNet.List<object> list4;
                    FilterFields(obj, out list3, out list4);
                    bw.WriteInt(list3.size);
                    int num39 = 0;
                    int size = list3.size;
                    while (num39 < size)
                    {
                        bw.Write(list3[num39]);
                        bw.WriteObject(list4[num39]);
                        num39++;
                    }
                    break;
                }
                case 0xff:
                    formatter.Serialize(bw.BaseStream, obj);
                    break;

                default:
                    Debug.LogError("Prefix " + prefix + " is not supported");
                    break;
            }
        }
    }
}

